package com.gupao.javavip.rpc.framework.server;

import com.gupao.javavip.rpc.framework.protocol.RPCRequest;
import com.gupao.javavip.rpc.framework.protocol.RPCServiceMapping;
import com.gupao.javavip.rpc.framework.protocol.RPCServiceProvider;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RequestHandlerHelper {
    public static volatile Map<String, ServiceMapping> serviceMappingMap = new ConcurrentHashMap<>();

    public static ServiceMapping getServiceMapping(RPCRequest request) {
        if (StringUtils.isEmpty(request.getService())) {
            throw new RuntimeException("必须指定请求的服务");
        }

        String serviceFlag = request.getService();

        String serviceVersion = "0";
        if (!StringUtils.isEmpty(request.getVersion())) {
            serviceVersion = request.getVersion();
        }

        serviceFlag += "#" + serviceVersion;

        if (serviceMappingMap.containsKey(serviceFlag)) {
            return serviceMappingMap.get(serviceFlag);
        }

        throw new RuntimeException("找不到服务:" + serviceFlag);
    }

    /**
     * 构建已发布的服务列表
     *
     * @param serviceProvider
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     */
    public static void buildServiceMapping(Object serviceProvider) throws ClassNotFoundException, NoSuchMethodException {
        Class serviceClass = serviceProvider.getClass();

        String serviceClassName = "";
        String serviceVersion = "";
        //获取RPC服务实现类的RPCService注解配置
        if (serviceClass.isAnnotationPresent(RPCServiceProvider.class)) {
            RPCServiceProvider rpcServiceProvider = (RPCServiceProvider) serviceClass.getAnnotation(RPCServiceProvider.class);
            serviceClassName = rpcServiceProvider.service().getName();
            serviceVersion = rpcServiceProvider.version();
        }

        //获取Method的RequestMapping配置
        Method[] methods = serviceClass.getMethods();
        for (Method method : methods) {
            if (!method.isAnnotationPresent(RPCServiceMapping.class)) {
                continue;
            }

            RPCServiceMapping requestMapping = method.getAnnotation(RPCServiceMapping.class);
            String serviceMethodName = requestMapping.method();

            ServiceMapping serviceMapping = new ServiceMapping();
            serviceMapping.setServiceProvider(serviceProvider);
            serviceMapping.setServiceName(serviceClassName + "#" + serviceMethodName + "#" + serviceVersion);
            serviceMapping.setMethod(method);

            serviceMappingMap.put(serviceMapping.getServiceName(), serviceMapping);
        }
    }
}
